home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 53142 / 53142.xpi / content / sodisplay.js < prev    next >
Text File  |  2009-12-07  |  13KB  |  368 lines

  1. /*##########################################################################
  2.     Copyright 2009 Tim Reid
  3.  
  4.     This file is part of the Stack Overflow Reputation Display extension
  5.     for Mozilla Firefox.
  6.  
  7.     Stack Overflow Reputation Display is free software: you can
  8.     redistribute it and/or modify it under the terms of the GNU General
  9.     Public License as published by the Free Software Foundation, either
  10.     version 3 of the License, or (at your option) any later version.
  11.  
  12.     Stack Overflow Reputation Display is distributed in the hope that it
  13.     will be useful, but WITHOUT ANY WARRANTY; without even the implied
  14.     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15.     See the GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public
  18.     License along with Stack Overflow Reputation Display. If not,
  19.     see <http://www.gnu.org/licenses/>.
  20. ##########################################################################*/
  21.  
  22. var SODisplay = function (init) {
  23.   this.id           = "autoid" + SODisplay.counter++;
  24.   this.currentscore = {};
  25.   this.document     = document;
  26.   this.requests     = [];
  27.  
  28.   this.elements = this.buildbasic(this.document);
  29.  
  30.   if (init)
  31.     for (var k in init)
  32.       this[k] = init[k];
  33.  
  34.   var me = this;
  35.   for (var i=0; i<this.elements.clicktargets.length; i++)
  36.     this.elements.clicktargets[i].addEventListener("click", function (e) { me.doclick(e); }, true);
  37.  
  38.   return this;
  39. };
  40.  
  41. SODisplay.counter = 0;
  42.  
  43. SODisplay.prototype = {
  44.   opener:       null,
  45.   textcolor:    null,
  46.  
  47.   buildbasic: function (doc) {
  48.     var elements = {
  49.                      reputation:      {
  50.                                         text: [],
  51.                                       },
  52.                      name:            {
  53.                                         text: [],
  54.                                       },
  55.                      siteicons:       [],
  56.                      usericons:       [],
  57.                      clicktargets:    [],
  58.                      badgecontainers: {},
  59.                      badgetext:       {},
  60.                      menuitems:       {},
  61.                      textitems:       {
  62.                                         statusbar: [],
  63.                                         popup: [],
  64.                                       },
  65.                    };
  66.  
  67.     //######################################################################
  68.     // Create popups for the display
  69.     //######################################################################
  70.     elements.panel = doc.createElement("statusbarpanel");
  71.     elements.panel.setAttribute("class", "sorepdisplay");
  72.     this.tooltipvisible = false;
  73.  
  74.     var h = doc.createElement("hbox");
  75.     h.setAttribute("align", "center");
  76.     h.setAttribute("class", "sorepdisplay sorepdisplay-statusbarpanelcontent");
  77.     elements.panel.appendChild(h);
  78.  
  79.     var i = doc.createElement("image");
  80.     i.setAttribute("class",  "sorepdisplay sorepdisplay-soicon");
  81.     i.setAttribute("height", 16);
  82.     i.setAttribute("width",  16);
  83.     h.appendChild(i);
  84.     elements.siteicons.push(i);
  85.     elements.clicktargets.push(i);
  86.  
  87.     var d = doc.createElement("description");
  88.     d.setAttribute("tooltiptext", "reputation score");
  89.     d.setAttribute("class",       "sorepdisplay sorepdisplay-score reputationtextcolor");
  90.     d.appendChild(doc.createTextNode("-"));
  91.     h.appendChild(d);
  92.     elements.reputation.text.push(d);
  93.     elements.textitems.popup.push(d);
  94.     elements.h = h;
  95.  
  96.     //######################################################################
  97.     // Create popups for the display
  98.     //######################################################################
  99.     elements.popupset = doc.createElement("popupset");
  100.     elements.popupset.setAttribute("class", "sorepdisplay");
  101.  
  102.     //######################################################################
  103.     // Create tooltip popup
  104.     //######################################################################
  105.     var t = doc.createElement("tooltip");
  106.     t.setAttribute("id",       "sorepdisplay-flair-" + this.id);
  107.     t.setAttribute("class",    "sorepdisplay");
  108.     t.setAttribute("position", "before_end");
  109.     elements.popupset.appendChild(t);
  110.  
  111.     var h3 = doc.createElement("hbox");
  112.     h3.setAttribute("width", "200");
  113.     t.appendChild(h3);
  114.  
  115.     var v = doc.createElement("vbox");
  116.     h3.appendChild(v);
  117.  
  118.     var i2 = doc.createElement("image");
  119.     i2.setAttribute("width",  "50");
  120.     i2.setAttribute("height", "50");
  121.     v.appendChild(i2);
  122.     elements.usericons.push(i2);
  123.  
  124.     var s = doc.createElement("spacer");
  125.     s.setAttribute("flex", "1");
  126.     v.appendChild(s);
  127.  
  128.     var s2 = doc.createElement("spacer");
  129.     s2.setAttribute("flex", "1");
  130.     h3.appendChild(s2);
  131.  
  132.     var v2 = doc.createElement("vbox");
  133.     v2.setAttribute("align", "end");
  134.     h3.appendChild(v2);
  135.  
  136.     var h4 = doc.createElement("hbox");
  137.     v2.appendChild(h4);
  138.  
  139.     var i3 = doc.createElement("image");
  140.     i3.setAttribute("height", 16);
  141.     i3.setAttribute("width", 16);
  142.     h4.appendChild(i3);
  143.     elements.siteicons.push(i3);
  144.  
  145.     var d3 = doc.createElement("description");
  146.     d3.setAttribute("class", "sorepdisplay sorepdisplay-name");
  147.     d3.appendChild(doc.createTextNode("-"));
  148.     h4.appendChild(d3);
  149.     elements.name.text.push(d3);
  150.     elements.textitems.popup.push(d3);
  151.  
  152.     var d4 = doc.createElement("description");
  153.     d4.setAttribute("class", "sorepdisplay sorepdisplay-score defaultreputationtextcolor");
  154.     d4.appendChild(doc.createTextNode("-"));
  155.     v2.appendChild(d4);
  156.     elements.reputation.text.push(d4);
  157.     elements.textitems.popup.push(d4);
  158.  
  159.     var h5 = doc.createElement("hbox");
  160.     v2.appendChild(h5);
  161.     elements.h5 = h5;
  162.  
  163.     //######################################################################
  164.     // Create context popup
  165.     //######################################################################
  166.     var mp = doc.createElement("menupopup");
  167.     mp.setAttribute("id", "sorepdisplay-popup-" + this.id);
  168.     elements.panel.setAttribute("context", "sorepdisplay-popup-" + this.id);
  169.     elements.popupset.appendChild(mp);
  170.  
  171.     elements.menuitems.options = doc.createElement("menuitem");
  172.     elements.menuitems.options.setAttribute("accesskey", "C");
  173.     elements.menuitems.options.setAttribute("label", "Configure...");
  174.     mp.appendChild(elements.menuitems.options);
  175.  
  176.     return elements;
  177.   },
  178.  
  179.   removebadges: function (badges, badgecontainers, badgetext) {
  180.     for (var i=0; i<badges.length; i++) {
  181.       var list = badgecontainers[badges[i]];
  182.       if (list)
  183.         for (var j=0; j<list.length; j++)
  184.           list[j].parentNode.removeChild(list[j]);
  185.       delete badgecontainers[badges[i]];
  186.     }
  187.   },
  188.  
  189.   addbadges: function (badges, element, badgecontainers, badgetext, badgetextclass) {
  190.     var doc = element.ownerDocument;
  191.     for (var k=0; k<badges.length; k++) {
  192.       if (!(badges[k] in badgecontainers))
  193.         badgecontainers[badges[k]] = [];
  194.       if (!(badges[k] in badgetext))
  195.         badgetext[badges[k]] = [];
  196.  
  197.       var hbox = doc.createElement("hbox");
  198.       hbox.setAttribute("tooltiptext", badges[k] + " badges");
  199.       hbox.setAttribute("align",       "center");
  200.       hbox.setAttribute("hidden",      "true");
  201.       element.appendChild(hbox);
  202.       badgecontainers[badges[k]].push(hbox);
  203.  
  204.       var bullet = doc.createElement("description");
  205.       bullet.setAttribute("class", "sorepdisplay sorepdisplay-badge" + (k+1));
  206.       bullet.appendChild(doc.createTextNode("\u25cf"));
  207.       hbox.appendChild(bullet);
  208.  
  209.       var text = doc.createElement("description");
  210.       text.setAttribute("class", "sorepdisplay sorepdisplay-badgecount " + badgetextclass);
  211.       text.appendChild(doc.createTextNode("-"));
  212.       hbox.appendChild(text);
  213.       badgetext[badges[k]].push(text);
  214.     }
  215.   },
  216.  
  217.   get account () {
  218.     return this._account;
  219.   },
  220.  
  221.   set account (account) {
  222.     this._account = account;
  223.     var badges = this.account.site.badges;
  224.     this.removebadges(badges, this.elements.badgecontainers, this.elements.badgetext);
  225.     this.addbadges(badges, this.elements.h,  this.elements.badgecontainers, this.elements.badgetext, "badgetextcolor");
  226.     this.addbadges(badges, this.elements.h5, this.elements.badgecontainers, this.elements.badgetext, "defaultbadgetextcolor");
  227.     for (var i=0; i<this.elements.siteicons.length; i++)
  228.       this.elements.siteicons[i].setAttribute("src", this.account.site.smallicon);
  229.   },
  230.  
  231.   showtooltip: function (b) {
  232.     if (b) {
  233.       this.elements.panel.setAttribute("tooltip", "sorepdisplay-flair-" + this.id);
  234.       this.tooltipvisible = true;
  235.     } else {
  236.       this.elements.panel.removeAttribute("tooltip");
  237.       this.tooltipvisible = false;
  238.     }
  239.   },
  240.  
  241.   preload: function (url) {
  242.     var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]  
  243.                         .createInstance(Components.interfaces.nsIXMLHttpRequest);  
  244.     req.open("GET", url, true);  
  245.     req.onload = function (e) {};
  246.     req.send(null);  
  247.     if (this.requests)
  248.       this.requests.push(req);
  249.   },
  250.  
  251.   get datauri () {
  252.     return this.account.site.uri("data", this.account.user);
  253.   },
  254.  
  255.   formatscore: function (score) {
  256.     var text = score.toString().replace(/,/g, "");
  257.     var newtext = text.replace(/(.*[0-9])([0-9][0-9][0-9])$/, "$1,$2");
  258.     do {
  259.       text = newtext;
  260.       newtext = text.replace(/(.*[0-9])([0-9][0-9][0-9]),$/, "$1,$2");
  261.     } while (text != newtext);
  262.  
  263.     return newtext;
  264.   },
  265.  
  266.   summary: function (count, colour) {
  267.     var text = count + " " + colour + " badge";
  268.     if (count != 1)
  269.       text += "s";
  270.     return text;
  271.   },
  272.  
  273.   updatedetails: function () {
  274.     var change;
  275.     var formattedreputation;
  276.  
  277.     var info = this.account.info;
  278.  
  279.     if (!info)
  280.       return;
  281.  
  282.     if (info.reputation) {
  283.       formattedreputation = this.formatscore(info.reputation);
  284.  
  285.       if ("reputation" in this.currentscore) {
  286.         if (info.reputation > this.currentscore.reputation) {
  287.           change = change || "up";
  288.         } else if (info.reputation < this.currentscore.reputation) {
  289.           change = change || "down";
  290.         }
  291.       }
  292.     } else {
  293.       formattedreputation = "-";
  294.     }
  295.  
  296.     if (info.avatar) {
  297.       var images = this.elements.usericons;
  298.       for (var j=0; j<images.length; j++)
  299.         if (images[j].getAttribute("src") != info.avatar) {
  300.           images[j].setAttribute("src", info.avatar);
  301.           this.preload(info.avatar);
  302.         }
  303.     }
  304.  
  305.     if (info.name) {
  306.       var names = this.elements.name.text;
  307.       for (var j=0; j<names.length; j++)
  308.         if (names[j].getAttribute("value") != info.name)
  309.           names[j].setAttribute("value", info.name);
  310.     }
  311.  
  312.     var reputations = this.elements.reputation.text;
  313.     for (var i=0; i<reputations.length; i++)
  314.       if (reputations[i].getAttribute("value") != formattedreputation)
  315.         reputations[i].setAttribute("value", formattedreputation);
  316.  
  317.     var badges = this.account.site.badges;
  318.     for (var i=0; i<badges.length; i++) {
  319.       var badge = badges[i];
  320.       if (info[badge]) {
  321.         var text = this.formatscore(info[badge]);
  322.         var texts = this.elements.badgetext[badge];
  323.         for (var j=0; j<texts.length; j++)
  324.           if (texts[j].getAttribute("value") != text)
  325.             texts[j].setAttribute("value", text);
  326.  
  327.         var tooltip = this.summary(text, badge);
  328.         var containers = this.elements.badgecontainers[badge];
  329.         for (var j=0; j<containers.length; j++) {
  330.           if (containers[j].getAttribute("tooltiptext") != tooltip)
  331.             containers[j].setAttribute("tooltiptext", tooltip);
  332.           containers[j].setAttribute("hidden", false);
  333.         }
  334.  
  335.         if (this.currentscore[badge]) {
  336.           if (info[badge] > this.currentscore[badge]) {
  337.             change = change || "up";
  338.           } else if (info[badge] < this.currentscore[badge]) {
  339.             change = change || "down";
  340.           }
  341.         }
  342.       } else {
  343.         var containers = this.elements.badgecontainers[badge];
  344.         if (containers)
  345.           for (var j=0; j<containers.length; j++)
  346.             containers[j].setAttribute("hidden", true);
  347.       }
  348.     }
  349.  
  350.     if (!this.tooltipvisible)
  351.       this.showtooltip(true);
  352.   },
  353.  
  354.   doclick: function (e) {
  355.     if (e.button == 0)
  356.       if (this.opener) {
  357.         var uri = this.account.site.uri(this.account.clickaction, this.account.user) ||
  358.                   this.account.site.uri("main");
  359.         if (uri)
  360.           this.opener(uri);
  361.       }
  362.   },
  363.  
  364.   registeropener: function (f) {
  365.     this.opener = f;
  366.   },
  367. };
  368.